package com.hmdp.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmdp.dto.Result;
import com.hmdp.dto.UserDTO;
import com.hmdp.entity.User;
import com.hmdp.mapper.UserMapper;
import com.hmdp.service.IUserService;
import com.hmdp.utils.RedisConstants;
import com.hmdp.utils.UserHolder;
import org.springframework.data.redis.connection.BitFieldSubCommands;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 虎哥
 * @since 2021-12-22
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    @Resource
    StringRedisTemplate stringRedisTemplate;

    @Override
    public UserDTO login(String phone) {
        // 查询是否有用户
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getPhone, phone);
        User user = this.getOne(wrapper);
        // 没有用户进行注册
        if(user == null) {
            user = new User();
            user.setPhone(phone);
            user.setNickName("hmdp_" + RandomUtil.randomString(9));
            this.save(user);
        }
        UserDTO userDTO = BeanUtil.copyProperties(user, UserDTO.class);
        return userDTO;
    }

    @Override
    public Result sign() {
        // 1. 获取用户ID
        Long userId = UserHolder.getUserId();
        // 2. 获取日期
        LocalDateTime now = LocalDateTime.now();
        // 3. 拼接KEY
        String keySuffix = now.format(DateTimeFormatter.ofPattern(":yyyyMM"));
        String key = RedisConstants.USER_SIGN_KEY + userId + keySuffix;
        // 4. 获取今天是本月第几天
        int dayOfMonth = now.getDayOfMonth();
        // 5. 写入Redis
        stringRedisTemplate.opsForValue().setBit(key, dayOfMonth - 1, true);
        return Result.ok("签到成功");
    }

    @Override
    public Result signCount() {
        // 1. 获取用户ID
        Long userId = UserHolder.getUserId();
        // 2. 获取日期
        LocalDateTime now = LocalDateTime.now();
        // 3. 拼接KEY
        String keySuffix = now.format(DateTimeFormatter.ofPattern(":yyyyMM"));
        String key = RedisConstants.USER_SIGN_KEY + userId + keySuffix;
        // 4. 获取今天是本月第几天
        int dayOfMonth = now.getDayOfMonth();
        // 5. 获取十进制位
        List<Long> result = stringRedisTemplate.opsForValue().bitField(key,
            BitFieldSubCommands.create()
                .get(BitFieldSubCommands.BitFieldType.unsigned(dayOfMonth)).valueAt(0) // 从0到最后一位
        );
        if(result == null || result.size() != 1) {
            return Result.ok(0);
        }
        // 6. 通过右移 + 位运算 计算签到次数
        Long value = result.get(0);
        int signCount = 0;
        while(value > 0) {
            long bit = value & 1;
            if(bit == 0) break;
            signCount += bit;
            value >>>= 1;
        }
        return Result.ok(signCount);
    }
}
